#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <cerrno>
#include <cstring>
#include <string>
#include <vector>
#include "task.hpp"

struct Channel
{
    Channel(int wfd, pid_t subprocessid, std::string name)
        : _wfd(wfd), _subprocessid(subprocessid), _name(name)
    {
    }

    int Get_wfd()
    {
        return _wfd;
    }
    pid_t Get_subprocessid()
    {
        return _subprocessid;
    }
    std::string Get_name()
    {
        return _name;
    }
    void CloseChannel()
    {
        close(_wfd);
    }
    void Wait()
    {
        int status;
        pid_t rid = waitpid(_subprocessid, &status, 0);
        if (rid > 0)
        {
            std::cout << rid << "  wait seccess process quit ... " << std::endl;
        }
    }
    ~Channel() {}
    int _wfd;
    pid_t _subprocessid;
    std::string _name;
};

// void Work(int rfd)
// {
//     while (true)
//     {
//         int command = 0;
//         int n = read(rfd, &command, sizeof(command));
//         if (n == sizeof(int))
//         {
//             std::cout << " pid is : " << getpid() << " handler task " << std::endl;
//             ExcuteTask(command);
//         }
//         else if (n == 0)
//         {
//             std::cout << " sub process : " << getpid() << " quit " << std::endl;
//             break;
//         }
//     }
// }
void CreateChannelAndSub(int num, std::vector<Channel> &channels,task_t task)
{
    for (int i = 0; i < num; i++)
    {
        // 创建一个管道
        int pipefd[2];
        int n = pipe(pipefd);
        if (n == -1)
        {
            std::cerr << "create pipe fail " << std::endl;
            exit(-1);
        }
        pid_t id = fork();
        if (id == 0)
        {
            close(pipefd[1]);
            dup2(pipefd[0],0);
            task();
            close(pipefd[0]);
            exit(0);
        }
        // 创建一个channel名称
        std::string channel_name = "Channel " + std::to_string(i);
        // 父进程
        close(pipefd[0]);
        // 父进程关系管道的w端
        channels.push_back(Channel(pipefd[1], id, channel_name));
    }
}

void SendTaskCommand(Channel &channel, int taskcommand)
{
    write(channel.Get_wfd(), &taskcommand, sizeof(taskcommand));
}
int NextChannel(int channelnum)
{
    static int next = 0;
    int channel = next;
    next++;
    next %= channelnum;
    return channel;
}
void CtrlProcessOnce(std::vector<Channel> &channels)
{
    sleep(1);
    // 选择一个任务
    int taskcommand = SelectTask();
    // 选择一个信道和进程
    int channel_index = NextChannel(channels.size());
    // 发送任务
    SendTaskCommand(channels[channel_index], taskcommand);
    std::cout << std::endl;
    std::cout << " taskcommand: " << taskcommand << " channel: "
              << channels[channel_index].Get_name() << " sub process : " << channels[channel_index].Get_subprocessid() << std::endl;
}
void CtrlProcess(std::vector<Channel> &channels, int num = -1)
{
    if (num == -1)
    {
        while (true)
        {
            CtrlProcessOnce(channels);
        }
    }
    else
    {
        for (int i = 0; i < num; i++)
        {
            CtrlProcessOnce(channels);
        }
    }
}
void CleanUpChannel(std::vector<Channel> channels)
{
    for (auto channel : channels)
    {
        channel.CloseChannel();
    }
    for (auto channel : channels)
    {
        channel.Wait();
    }
}
int main(int Argc, char *Argv[])
{
    if (Argc != 2)
    {
        std::cerr << "usage :  " << Argv[0] << "processnum" << std::endl;
        return 1;
    }

    LoadTask();
    // 创建信道和子进程

    int num = std::stoi(Argv[1]);
    std::vector<Channel> channels;
    CreateChannelAndSub(num, channels,Work);

    // 通过channel控制子进程
    CtrlProcess(channels, 10);

    // //回收管道的子进程，1：关闭读端 2：回收子进程
    CleanUpChannel(channels);


    return 0;
}